/* 
 * "Small Hello World" example. 
 * 
 * This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
 * the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example 
 * designs. It requires a STDOUT  device in your system's hardware. 
 *
 * The purpose of this example is to demonstrate the smallest possible Hello 
 * World application, using the Nios II HAL library.  The memory footprint
 * of this hosted application is ~332 bytes by default using the standard 
 * reference design.  For a more fully featured Hello World application
 * example, see the example titled "Hello World".
 *
 * The memory footprint of this example has been reduced by making the
 * following changes to the normal "Hello World" example.
 * Check in the Nios II Software Developers Manual for a more complete 
 * description.
 * 
 * In the SW Application project (small_hello_world):
 *
 *  - In the C/C++ Build page
 * 
 *    - Set the Optimization Level to -Os
 * 
 * In System Library project (small_hello_world_syslib):
 *  - In the C/C++ Build page
 * 
 *    - Set the Optimization Level to -Os
 * 
 *    - Define the preprocessor option ALT_NO_INSTRUCTION_EMULATION 
 *      This removes software exception handling, which means that you cannot 
 *      run code compiled for Nios II cpu with a hardware multiplier on a core 
 *      without a the multiply unit. Check the Nios II Software Developers 
 *      Manual for more details.
 *
 *  - In the System Library page:
 *    - Set Periodic system timer and Timestamp timer to none
 *      This prevents the automatic inclusion of the timer driver.
 *
 *    - Set Max file descriptors to 4
 *      This reduces the size of the file handle pool.
 *
 *    - Check Main function does not exit
 *    - Uncheck Clean exit (flush buffers)
 *      This removes the unneeded call to exit when main returns, since it
 *      won't.
 *
 *    - Check Don't use C++
 *      This builds without the C++ support code.
 *
 *    - Check Small C library
 *      This uses a reduced functionality C library, which lacks  
 *      support for buffering, file IO, floating point and getch(), etc. 
 *      Check the Nios II Software Developers Manual for a complete list.
 *
 *    - Check Reduced device drivers
 *      This uses reduced functionality drivers if they're available. For the
 *      standard design this means you get polled UART and JTAG UART drivers,
 *      no support for the LCD driver and you lose the ability to program 
 *      CFI compliant flash devices.
 *
 *    - Check Access device drivers directly
 *      This bypasses the device file system to access device drivers directly.
 *      This eliminates the space required for the device file system services.
 *      It also provides a HAL version of libc services that access the drivers
 *      directly, further reducing space. Only a limited number of libc
 *      functions are available in this configuration.
 *
 *    - Use ALT versions of stdio routines:
 *
 *           Function                  Description
 *        ===============  =====================================
 *        alt_printf       Only supports %s, %x, and %c ( < 1 Kbyte)
 *        alt_putstr       Smaller overhead than puts with direct drivers
 *                         Note this function doesn't add a newline.
 *        alt_putchar      Smaller overhead than putchar with direct drivers
 *        alt_getchar      Smaller overhead than getchar with direct drivers
 *
 */

#include "sys/alt_stdio.h"
#include "w5200.h"
#include "at24c16.h"
#include <stdio.h>
#include "unistd.h"
#include "iic.h"
#include "commandloop.h"
#include "helper.h"
#include "check_reset.h"

int main()
{ 
	alt_32 rc = 0, RecvLength = 0, SendLegnth = 0;
	alt_u8 test_send_buf[TOTAL_LENGTH];
	alt_u8 test_recv_buf[TOTAL_LENGTH];
	alt_u8 alive = 8;
	int sock_status[SOCKETS];
	int i = 0;
	for (i=0; i<SOCKETS; ++i)
		sock_status[i] = W5200RT_CLOSED;

//	for(i=0; i<0; ++i)
	for(;;)
	{
		//initial sockets
		printf_c("Entering Main Loop...\n");
		if(/*W5200CheckLink() < 0 || */alive == 0)
		{
			printf_c("Reseting ...\n");
			SetW5200Reset();
			for (i=0; i<SOCKETS; ++i)
				sock_status[i] = W5200RT_CLOSED;
		}

		W5200GlobalInit();
		alive = 0;
		for (i=0; i<SOCKETS; ++i)
		{
			printf_c("Initializing ...\n");
			if (sock_status[i] == W5200RT_CLOSED)
				sock_status[i] = W5200Initial(1000, i);

			printf_c("Initialized result @ %d : %d.\n", i, sock_status[i]);

			if (sock_status[i] != W5200RT_INITED)
				sock_status[i] = W5200RT_TO_BE_CLOSED;
			else
				alive ++;
		}
		if(alive == 0)
			continue;

		while(1)
		{
			for(i=0; i<SOCKETS; ++i)
			{
				if(sock_status[i] == W5200RT_TO_BE_CLOSED)
				{
					printf_c("TCP command error, close socket %d!!\n", i);
					W5200CloseSocket(i);
					sock_status[i] = W5200Initial(1000, i);
				}
				if (sock_status[i] == W5200RT_INITED)
				{
//					printf_c("Checking connection @ %d.\n", i);
					rc = W5200CheckEstablish(10, i);
					// no connection;
					if (rc != W5200RT_SUCCESS)
					{
//						printf_c("No connection @ %d.\n", i);
						continue;
					}// empty buffer;
//					printf_c("Connected @ %d.\n", i);
					if((RecvLength = W5200CheckRecv(i)) == 0)
						continue;
					printf_c("Got %d in buffer @ socket %d\n", RecvLength, i);

					if(RecvLength < 0 || RecvLength > TOTAL_LENGTH)
					{
						sock_status[i] = W5200RT_TO_BE_CLOSED;
						continue;
					}
					W5200RecvBuf(&test_recv_buf[0], RecvLength, i);

					SendLegnth = DecodeRevBuf(&test_recv_buf[0], &test_send_buf[0], RecvLength);

					// incorrect command detect
					if(SendLegnth < 0)
					{
						printf_c("DecodeRevBuf error.\n");
						//sock_status[i] = W5200RT_TO_BE_CLOSED;
						continue;
					}
					rc = W5200SendBuf(&test_send_buf[0], SendLegnth, i);
					if(rc < 0)
					{
						printf_c("Send Ack error.\n");
						sock_status[i] = W5200RT_TO_BE_CLOSED;
						continue;
					}
				}
			}

			alive = 8;
			for (i=0; i<SOCKETS; ++i)
			{
				if (sock_status[i] == W5200RT_TO_BE_CLOSED)
					alive --;
			}
			if(alive == 0)
			{
				printf_c("All sockets dead.\n");
				break;
			}
		}

		for(i=0; i<SOCKETS; ++i)
		{
			if(sock_status[i] == W5200RT_TO_BE_CLOSED)
			{
				printf_c("TCP command error, close socket!!\n");
				W5200CloseSocket(i);
				sock_status[i] = W5200RT_CLOSED;
			}
		}
		usleep(1000 * 1000);
	}
//	return 0;

	for(;;)
	{
		rc = W5200Initial(1000, 0);
		if(rc < 0)
		{
			SetW5200Reset();
			printf_c("W5200Initial failed\n");
			continue;
		}

		rc = W5200CheckEstablish(1000, 0);
		if(rc < 0)
		{
			printf_c(" W5200CheckEstablish failed\n");
			continue;
		}

		while(1)
		{
			// check link status
			if(W5200CheckLink() < 0)
				break;

			if((RecvLength = W5200CheckRecv(0)) == 0)
				continue;
			printf_c("Got %d in buffer\n", RecvLength);

			if(RecvLength < 0 || RecvLength > TOTAL_LENGTH)
				break;

			if(RecvLength > 0)
			{
				// recive data
				W5200RecvBuf(&test_recv_buf[0], RecvLength, 0);

				SendLegnth = DecodeRevBuf(&test_recv_buf[0], &test_send_buf[0], RecvLength);

				// incorrect command detect
				if(SendLegnth < 0)
				{
					printf_c("DecodeRevBuf error.\n");
					break;
				}

				rc = W5200SendBuf(&test_send_buf[0], SendLegnth, 0);

				if(rc < 0)
					break;
			}
//			else
//				usleep(1000 * 1000);
		}
		printf_c("TCP command error, close socket!!\n");
		W5200CloseSocket(0);
		usleep(200 * 1000);
	}
	return 0;

}

